home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-08-22 | 79.7 KB | 3,075 lines |
- #import <math.h>
- #import <appkit/workspaceRequest.h>
- #import <misckit/MiscString.h>
-
- #import "PSWEnding.h"
- #import "PSWUControl.h"
- #import "RTFDescription.h"
- #import "UndoManager.h"
-
- #import "Tree.h"
-
- //************************************************************************
- // static c functions declaration
-
- // static functions for layouting
- static void setRectFromPolygon(NXRect *rect, Polygon *aPol, const NXPoint *ipu, const NXPoint *ipl,
- NXCoord *low, NXCoord *loh);
- static NXCoord merge(Polygon *c1,Polygon *c2, NXZone *zone);
- static NXCoord offset(NXCoord p1,NXCoord p2,NXCoord a1,NXCoord a2,
- NXCoord b1,NXCoord b2);
- static Polyline *bridge(Polyline *line1,Polyline *line2,NXCoord x1,NXCoord y1,
- NXCoord x2,NXCoord y2, NXZone *zone);
- static Polyline *allocLine(NXCoord aX,NXCoord aY,Polyline *aLink, NXZone *zone);
- static Polyline *copyPolyline(Polyline *aSource,Polyline **aTail, NXZone *zone);
- static void freePolyline(Polyline *aLine);
- static void partialFreePolyline(Polyline *aLine, Polyline *toEnd);
-
- // static functions for calculating path intersection
- static BOOL straddles(const NXPoint *p1, const NXPoint *p2, const NXPoint *p3, const NXPoint *p4);
-
- // static variables for general use
- static float controlPts[8],controlX,controlY,officialFontSize;
- static char controlChars[5];
- static char controlPrimChars[5];
- static NXAtom fontname;
- static ButtonCell *attachCell, *soundCell;
- static Cell *zippedCell;
- static NXRect attachCellFrame, soundCellFrame, zippedCellFrame;
- static UPath *arrowEnding, *doubleEnding, *circleEnding;
- static UPath *parentArrowEnding, *parentDoubleEnding, *parentCircleEnding;
-
- // static variables for diagram2 streaming
- #import "DGVariables.h"
-
- @interface Tree(PrivateMethods)
-
- - attachParent:(NXCoord)h;
- - layoutLeaf;
- - (NXCoord)join;
- - makePath;
- - changeText;
- - changePos;
- - fillGPathParams;
- - calcWidthHeight;
- - internalCopyFromZone:(NXZone *)zone parent:aParent;
- - calcIntersection:(NXPoint *)ip angle:(float *)alpha toPoint:(const NXPoint *)aPoint;
-
- @end
-
- @implementation Tree
-
- //************************************************************************
- // creating and destroying
-
- + initialize
- {
- int i;
-
- #ifndef FILTER
-
- NXRect dummy;
- id dummyId;
-
- #endif
-
- if(self == [Tree class]){
- [Tree setVersion:1];
- fontname = NXUniqueString("ControlPoints");
- PSWDefineFont(fontname);
- officialFontSize = 8.0;
- controlPts[6] = 0;
- controlPts[7] = 0;
- controlChars[4] = 0;
- controlPrimChars[4] = 0;
- for(i = 0;i < 4;i++){
- controlChars[i] = 'a';
- controlPrimChars[i] = 'e';
- }
-
- #ifndef FILTER
-
- dummyId = [NXImage findImageNamed:"NXLinkButton"];
- if([dummyId lockFocus])
- [dummyId unlockFocus];
- dummyId = [NXImage findImageNamed:"NXLinkButtonH"];
- if([dummyId lockFocus])
- [dummyId unlockFocus];
- dummyId = [NXImage findImageNamed:"zipped"];
- if([dummyId lockFocus])
- [dummyId unlockFocus];
- dummyId = [NXImage findImageNamed:"soundMarker"];
- if([dummyId lockFocus])
- [dummyId unlockFocus];
- dummyId = [NXImage findImageNamed:"soundMarkerH"];
- if([dummyId lockFocus])
- [dummyId unlockFocus];
- NXSetRect(&dummy, 0, 0, 100, 100);
- attachCell = [[ButtonCell alloc] initIconCell:"NXLinkButton"];
- [attachCell setAltIcon:"NXLinkButtonH"];
- [attachCell setBordered:NO];
- [attachCell setHighlightsBy:NX_CONTENTS];
- [attachCell setIconPosition:NX_ICONONLY];
- [attachCell calcCellSize:&(attachCellFrame.size) inRect:&dummy];
- zippedCell = [[Cell alloc] initIconCell:"zipped"];
- [zippedCell setBordered:NO];
- [zippedCell calcCellSize:&(zippedCellFrame.size) inRect:&dummy];
- soundCell = [[ButtonCell alloc] initIconCell:"soundMarker"];
- [soundCell setAltIcon:"soundMarkerH"];
- [soundCell setBordered:NO];
- [soundCell setHighlightsBy:NX_CONTENTS];
- [soundCell setIconPosition:NX_ICONONLY];
- [soundCell calcCellSize:&(soundCellFrame.size) inRect:&dummy];
-
- #endif
-
- arrowEnding = [[UPath alloc] init];
- [arrowEnding moveto:0 :0];
- [arrowEnding rlineto:-10 :5];
- [arrowEnding rlineto:3 :-5];
- [arrowEnding rlineto:-3 :-5];
- [arrowEnding closepath];
- doubleEnding = [[UPath alloc] init];
- [doubleEnding moveto:0 :0];
- [doubleEnding rlineto:-5 :5];
- [doubleEnding rlineto:2 :-5];
- [doubleEnding rlineto:-7 :5];
- [doubleEnding rlineto:2 :-5];
- [doubleEnding rlineto:-2 :-5];
- [doubleEnding rlineto:7 :5];
- [doubleEnding rlineto:-2 :-5];
- [doubleEnding closepath];
- circleEnding = [[UPath alloc] init];
- [circleEnding moveto:0 :0];
- [circleEnding arc:-3 :0 :3 :0 :360];
- parentArrowEnding = [[UPath alloc] init];
- [parentArrowEnding moveto:0 :0];
- [parentArrowEnding rlineto:10 :5];
- [parentArrowEnding rlineto:-3 :-5];
- [parentArrowEnding rlineto:3 :-5];
- [parentArrowEnding closepath];
- parentDoubleEnding = [[UPath alloc] init];
- [parentDoubleEnding moveto:0 :0];
- [parentDoubleEnding rlineto:5 :5];
- [parentDoubleEnding rlineto:-2 :-5];
- [parentDoubleEnding rlineto:7 :5];
- [parentDoubleEnding rlineto:-2 :-5];
- [parentDoubleEnding rlineto:2 :-5];
- [parentDoubleEnding rlineto:-7 :5];
- [parentDoubleEnding rlineto:2 :-5];
- [parentDoubleEnding closepath];
- parentCircleEnding = [[UPath alloc] init];
- [parentCircleEnding moveto:6 :0];
- [parentCircleEnding arc:3 :0 :3 :0 :360];
- }
- return self;
- }
-
- - initLabel:(const char *)aLabel props:(Properties *)aProps
- {
- [super init];
- contour.lower.head = contour.upper.head = NULL;
- contour.lower.tail = contour.upper.tail = NULL;
- parent = child = sibling = nil;
- delegate = nil;
- hasVerknuepfung = NO;
- verknuepfung = nil;
- hasSound = NO;
- geraeusch = nil;
- offset.x = offset.y = 0.0;
- pos.x = pos.y = 0.0;
- selected = NO;
- updateLayout = YES;
- if(aLabel)
- textCell = [[TextFieldCell allocFromZone:[self zone]] initTextCell:aLabel];
- else
- textCell = [[TextFieldCell allocFromZone:[self zone]] initTextCell:aProps->defaultNodeName];
- [textCell setBordered:NO];
- [textCell setBackgroundTransparent:YES];
- [textCell setTextColor:aProps->textColor];
- [textCell setAlignment:NX_CENTERED];
- nodeDescription = [[RTFDescription allocFromZone:[self zone]] init];
- zipped = aProps->zipped;
- border = aProps->border;
- shadow = aProps->shadow;
- fill = aProps->fill;
- outline = aProps->outline;
- linkKind = aProps->linkKind;
- biegFactor = aProps->biegFactor;
- parentDistance = aProps->parentDistance;
- fillColor = aProps->fillColor;
- outlineColor = aProps->outlineColor;
- shadowColor = aProps->shadowColor;
- ending = aProps->ending;
- parentEnding = aProps->parentEnding;
- gpath = [[UPath allocFromZone:[self zone]] init];
- pathKind = aProps->pathKind;
- deltaShadow.x = deltaShadow.y = 3;
- placer.rect[0] = placer.rect[1] = 6;
- placer.roundRect[0] = placer.roundRect[1] = 6;
- placer.roundRect[2] = 3;
- placer.ellipse[0] = 6;
- placer.ellipse[1] = 4;
- placer.rhomb[0] = 12;
- placer.rhomb[1] = 3;
- placer.hexagon[0] = 6;
- placer.hexagon[1] = 6;
- placer.hexagon[2] = 1;
- [self makePath];
- return self;
- }
-
- - free
- {
- [nodeDescription free];
- if(contour.lower.head)
- freePolyline(contour.lower.head);
- if(contour.upper.head)
- freePolyline(contour.upper.head);
- if(child)
- [child free];
- if(sibling)
- [sibling free];
- [gpath free];
- if(verknuepfung)
- [verknuepfung free];
- if(geraeusch)
- [geraeusch free];
- [textCell free];
- return [super free];
- }
-
- - copyFromZone:(NXZone *)zone
- {
- Tree *theCopy;
-
- theCopy = [super copyFromZone:zone];
- theCopy->contour.upper.head = contour.upper.tail = NULL;
- theCopy->contour.lower.head = contour.lower.tail = NULL;
- theCopy->updateLayout = YES;
- theCopy->parent = nil;
- theCopy->sibling = nil;
- if(child)
- theCopy->child = [child internalCopyFromZone:zone parent:theCopy];
- else
- theCopy->child = nil;
- theCopy->selected = NO;
- theCopy->gpath = [gpath copyFromZone:zone];
- theCopy->nodeDescription = [nodeDescription copyFromZone:zone];
- theCopy->delegate = nil;
- if(verknuepfung)
- theCopy->verknuepfung = [verknuepfung copyFromZone:zone];
- else
- theCopy->verknuepfung = nil;
- if(geraeusch)
- theCopy->geraeusch = [geraeusch copyFromZone:zone];
- else
- theCopy->geraeusch = nil;
- theCopy->textCell = [textCell copyFromZone:zone];
- return theCopy;
- }
-
- //************************************************************************
- // layout and drawing
-
- - involved:(const NXRect *)aRect addTo:aList link:aPath
- {
- NXRect rect,dummyRect;
- NXPoint point,mp,parentPoint,childPoint;
- NXCoord dist;
-
- if(parent && parent->zipped)
- return self;
- [self getBounds:&rect];
- if(aRect == NULL || NXIntersectsRect(&rect,aRect))
- [aList addObject:self];
- if(parent){
- [parent linkPoint:&point];
- [self linkPoint:&mp];
- if(linkKind){
- [parent linkParentPoint:&parentPoint];
- [self linkChildPoint:&childPoint];
- }
- dist = ABS(point.y - mp.y);
- if(dist > 0)
- NXSetRect(&dummyRect,MIN(mp.x,point.x) - 0.5,MIN(mp.y,point.y) - 0.5,
- ABS(point.x - mp.x) + 1,dist + 1);
- else
- NXSetRect(&dummyRect,MIN(mp.x,point.x),mp.y - 0.5,
- ABS(point.x - mp.x),1.0);
- if(aRect == NULL || NXIntersectsRect(aRect,&dummyRect)){
- if(linkKind == 0){
- [aPath moveto:point.x :point.y];
- [aPath lineto:mp.x :mp.y];
- } else {
- [aPath moveto:point.x :point.y];
- [aPath lineto:parentPoint.x :parentPoint.y];
- [aPath lineto:childPoint.x :childPoint.y];
- [aPath lineto:mp.x :mp.y];
- }
- }
- }
- if(child)
- [child involved:aRect addTo:aList link:aPath];
- if(sibling)
- [sibling involved:aRect addTo:aList link:aPath];
- return self;
- }
-
- - getBounds:(NXRect *)rect
- {
- NXRect dummy;
- NXCoord dxy, dwh;
-
- NXSetRect(rect,pos.x,pos.y,width,height);
- if(selected){
- dxy = MAX(5, linewidth);
- dwh = MAX(10, linewidth);
- rect->origin.x -= dxy;
- rect->origin.y -= dxy;
- rect->size.width += dwh;
- rect->size.height += dwh;
- }
- if(shadow){
- rect->size.width += deltaShadow.x;
- rect->size.height += deltaShadow.y;
- }
- if((ending && parent) || (parentEnding && child)){
- NXInsetRect(rect, -15, -15);
- }
- if(hasVerknuepfung){
- NXSetRect(&dummy, pos.x + 23,
- pos.y - linewidth - attachCellFrame.size.height - 1,
- attachCellFrame.size.width,
- attachCellFrame.size.height);
- NXUnionRect(&dummy, rect);
- }
- if(zipped){
- NXSetRect(&dummy, pos.x + 7,
- pos.y - linewidth - zippedCellFrame.size.height - 1,
- zippedCellFrame.size.width,
- zippedCellFrame.size.height);
- NXUnionRect(&dummy, rect);
- }
- if(hasSound){
- NXSetRect(&dummy, pos.x + 37,
- pos.y - linewidth - soundCellFrame.size.height - 1,
- soundCellFrame.size.width,
- soundCellFrame.size.height);
- NXUnionRect(&dummy, rect);
- }
- return self;
- }
-
- - getTreeBounds:(NXRect *)rect lowerWidth:(NXCoord *)lowW lowerHeight:(NXCoord *)lowH
- {
- NXPoint p1,p2;
-
- p1.x = pos.x - border;
- p1.y = pos.y - border;
- p2.x = pos.x - border;
- p2.y = pos.y + height + border;
- setRectFromPolygon(rect, &contour, &p1, &p2, lowW, lowH);
- NXInsetRect(rect,border - linewidth,border - linewidth);
- if(shadow){
- rect->size.width += deltaShadow.x;
- rect->size.height += deltaShadow.y;
- }
- return self;
- }
-
- - hit:(HitPath *)hitUPath
- {
- BOOL didHit;
- id dummy;
-
- didHit = [hitUPath hitPathFill:gpath];
- if(didHit)
- return self;
- else if(child){
- dummy = [child hit:hitUPath];
- if(dummy)
- return dummy;
- else if(sibling)
- return [sibling hit:hitUPath];
- } else if(sibling)
- return [sibling hit:hitUPath];
- return nil;
- }
-
- - hitAttachment:(const NXPoint *)aPoint :(BOOL *)theAttach
- {
- BOOL didHit;
- id dummy;
- NXRect dummyRect;
-
- *theAttach = NO;
- if(hasVerknuepfung){
- NXSetRect(&dummyRect,
- pos.x + 23,
- pos.y - linewidth - attachCellFrame.size.height - 1,
- attachCellFrame.size.width,
- attachCellFrame.size.height);
- didHit = NXPointInRect(aPoint, &dummyRect);
- } else
- didHit = NO;
- if(didHit){
- *theAttach = YES;
- return self;
- }
- if(hasSound){
- NXSetRect(&dummyRect,
- pos.x + 37,
- pos.y - linewidth - soundCellFrame.size.height - 1,
- soundCellFrame.size.width,
- soundCellFrame.size.height);
- didHit = NXPointInRect(aPoint, &dummyRect);
- } else
- didHit = NO;
- if(didHit)
- return self;
- if(child){
- dummy = [child hitAttachment:aPoint :theAttach];
- if(dummy)
- return dummy;
- else if(sibling)
- return [sibling hitAttachment:aPoint :theAttach];
- } else if(sibling)
- return [sibling hitAttachment:aPoint :theAttach];
- return nil;
- }
-
- - activateAttachment:(NXEvent *)event inView:aView
- {
- NXPoint p;
- NXRect dummyRect;
- id result;
-
- if(!hasVerknuepfung)
- return self;
- attachCellFrame.origin.x = pos.x + 23;
- attachCellFrame.origin.y = pos.y - linewidth - attachCellFrame.size.height - 1;
- [attachCell highlight:&attachCellFrame inView:aView lit:YES];
- [[aView window] flushWindow];
- while(event->type != NX_MOUSEUP)
- event = [NXApp getNextEvent:NX_MOUSEUPMASK];
- p = event->location;
- [aView convertPoint:&p fromView:nil];
- dummyRect = attachCellFrame;
- if(NXPointInRect(&p, &dummyRect)){
- [[Application workspace] openFile:[verknuepfung sourceFilename]];
- result = self;
- } else
- result = nil;
- [attachCell highlight:&attachCellFrame inView:aView lit:NO];
- [[aView window] flushWindow];
- return result;
- }
-
- - activateSound:(NXEvent *)event inView:aView
- {
- NXPoint p;
- NXRect dummyRect;
- id result;
-
- if(!hasSound)
- return self;
- soundCellFrame.origin.x = pos.x + 37;
- soundCellFrame.origin.y = pos.y - linewidth - soundCellFrame.size.height - 1;
- [soundCell highlight:&soundCellFrame inView:aView lit:YES];
- [[aView window] flushWindow];
- while(event->type != NX_MOUSEUP)
- event = [NXApp getNextEvent:NX_MOUSEUPMASK];
- p = event->location;
- [aView convertPoint:&p fromView:nil];
- dummyRect = soundCellFrame;
- if(NXPointInRect(&p, &dummyRect)){
- [geraeusch play];
- result = self;
- } else
- result = nil;
- [soundCell highlight:&soundCellFrame inView:aView lit:NO];
- [[aView window] flushWindow];
- return result;
- }
-
- - drawNodeShadow:(DrawState *)aState
- {
- NXPoint dummy;
-
- if(shadow){
- if(!NXEqualColor(aState->color,shadowColor)){
- aState->color = shadowColor;
- NXSetColor(shadowColor);
- }
- dummy = pos;
- pos.x += deltaShadow.x;
- pos.y += deltaShadow.y;
- [self changePos];
- [gpath send:dps_ufill cached:YES];
- pos = dummy;
- [self changePos];
- }
- return self;
- }
-
- - drawNodeFill:(DrawState *)aState
- {
- if(fill){
- if(!NXEqualColor(aState->color,fillColor)){
- aState->color = fillColor;
- NXSetColor(fillColor);
- }
- [gpath send:dps_ufill cached:YES];
- }
- return self;
- }
-
- - drawNodeEnding:(DrawState *)aState
- {
- NXPoint outPoint,iPoint;
- float rotAngle;
- Tree *ptr;
-
- if(ending != ENDING_NONE && parent){
- if(linkKind)
- [self linkChildPoint:&outPoint];
- else
- [parent linkPoint:&outPoint];
- if(!NXEqualColor(aState->color,NX_COLORBLACK)){
- aState->color = NX_COLORBLACK;
- NXSetColor(NX_COLORBLACK);
- }
- if(aState->linewidth != 0.15){
- aState->linewidth = 0.15;
- PSsetlinewidth(0.15);
- }
- [self calcIntersection:&iPoint angle:&rotAngle toPoint:&outPoint];
- switch(ending){
- case ENDING_ARROW:
- PSWEndingSolid(arrowEnding->bboxParams, arrowEnding->sizeParams + 4,
- arrowEnding->bboxOps, arrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_HOLLOW:
- PSWEndingHollow(arrowEnding->bboxParams, arrowEnding->sizeParams + 4,
- arrowEnding->bboxOps, arrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_DOUBLE:
- PSWEndingSolid(doubleEnding->bboxParams, doubleEnding->sizeParams + 4,
- doubleEnding->bboxOps, doubleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_SOLID:
- PSWEndingSolid(circleEnding->bboxParams, circleEnding->sizeParams + 4,
- circleEnding->bboxOps, circleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_CIRCLE:
- PSWEndingHollow(circleEnding->bboxParams, circleEnding->sizeParams + 4,
- circleEnding->bboxOps, circleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- default:
- break;
- }
- }
- if(parentEnding != ENDING_NONE && child){
- if(linkKind){
- [self linkParentPoint:&outPoint];
- [self calcIntersection:&iPoint angle:&rotAngle toPoint:&outPoint];
- switch(parentEnding){
- case ENDING_ARROW:
- PSWEndingSolid(parentArrowEnding->bboxParams, parentArrowEnding->sizeParams + 4,
- parentArrowEnding->bboxOps, parentArrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_HOLLOW:
- PSWEndingHollow(parentArrowEnding->bboxParams, parentArrowEnding->sizeParams + 4,
- parentArrowEnding->bboxOps, parentArrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_DOUBLE:
- PSWEndingSolid(parentDoubleEnding->bboxParams, parentDoubleEnding->sizeParams + 4,
- parentDoubleEnding->bboxOps, parentDoubleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_SOLID:
- PSWEndingSolid(parentCircleEnding->bboxParams, parentCircleEnding->sizeParams + 4,
- parentCircleEnding->bboxOps, parentCircleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_CIRCLE:
- PSWEndingHollow(parentCircleEnding->bboxParams, parentCircleEnding->sizeParams + 4,
- parentCircleEnding->bboxOps, parentCircleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- default:
- break;
- }
- } else {
- for(ptr = child;ptr;ptr = ptr->sibling){
- [ptr linkPoint:&outPoint];
- [self calcIntersection:&iPoint angle:&rotAngle toPoint:&outPoint];
- switch(parentEnding){
- case ENDING_ARROW:
- PSWEndingSolid(parentArrowEnding->bboxParams, parentArrowEnding->sizeParams + 4,
- parentArrowEnding->bboxOps, parentArrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_HOLLOW:
- PSWEndingHollow(parentArrowEnding->bboxParams, parentArrowEnding->sizeParams + 4,
- parentArrowEnding->bboxOps, parentArrowEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_DOUBLE:
- PSWEndingSolid(parentDoubleEnding->bboxParams, parentDoubleEnding->sizeParams + 4,
- parentDoubleEnding->bboxOps, parentDoubleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_SOLID:
- PSWEndingSolid(parentCircleEnding->bboxParams, parentCircleEnding->sizeParams + 4,
- parentCircleEnding->bboxOps, parentCircleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- case ENDING_CIRCLE:
- PSWEndingHollow(parentCircleEnding->bboxParams, parentCircleEnding->sizeParams + 4,
- parentCircleEnding->bboxOps, parentCircleEnding->sizeOps + 2,iPoint.x,iPoint.y,rotAngle);
- break;
- default:
- break;
- }
- }
- }
- }
- return self;
- }
-
- - drawNodeOutline:(DrawState *)aState knobs:(BOOL)aBool
- {
- if(outline){
- if(!NXEqualColor(aState->color,outlineColor)){
- aState->color = outlineColor;
- NXSetColor(outlineColor);
- }
- if(aState->linewidth != linewidth){
- aState->linewidth = linewidth;
- PSsetlinewidth(linewidth);
- }
- [gpath send:dps_ustroke cached:YES];
- }
- if(selected && aBool){
- if(delegate)
- PSselectfont(fontname,officialFontSize / [delegate docScale]);
- else
- PSselectfont(fontname,officialFontSize);
- aState->font = nil;
- if(!NXEqualColor(aState->color,NX_COLORBLACK)){
- aState->color = NX_COLORBLACK;
- NXSetColor(NX_COLORBLACK);
- }
- controlX = gpath->bbox[0];
- controlY = gpath->bbox[1];
- controlPts[0] = gpath->bbox[2] - gpath->bbox[0];
- controlPts[1] = 0;
- controlPts[2] = 0;
- controlPts[3] = gpath->bbox[3] - gpath->bbox[1];
- controlPts[4] = -controlPts[0];
- controlPts[5] = 0;
- PSWDrawControlPoints(controlX,controlY,controlPts,8,controlChars);
- if(!NXEqualColor(aState->color,NX_COLORDKGRAY)){
- aState->color = NX_COLORDKGRAY;
- NXSetColor(NX_COLORDKGRAY);
- }
- PSWDrawControlPoints(controlX,controlY,controlPts,8,controlPrimChars);
- }
- return self;
- }
-
- - drawNodeCellsInView:aView attachments:(BOOL)aBool
- {
- if(hasVerknuepfung && aBool){
- attachCellFrame.origin.x = pos.x + 23;
- attachCellFrame.origin.y = pos.y - linewidth - attachCellFrame.size.height - 1;
- [attachCell drawSelf:&attachCellFrame inView:aView];
- }
- if(hasSound && aBool){
- soundCellFrame.origin.x = pos.x + 37;
- soundCellFrame.origin.y = pos.y - linewidth - soundCellFrame.size.height - 1;
- [soundCell drawSelf:&soundCellFrame inView:aView];
- }
- textCellFrame.origin.x = pos.x + deltaText.x;
- textCellFrame.origin.y = pos.y + deltaText.y;
- [textCell drawSelf:&textCellFrame inView:aView];
- if(aBool && zipped){
- zippedCellFrame.origin.x = pos.x + 7;
- zippedCellFrame.origin.y = pos.y - linewidth - zippedCellFrame.size.height - 1;
- [zippedCell drawSelf:&zippedCellFrame inView:aView];
- }
- return self;
- }
-
- - setOffset:(NXCoord)aX :(NXCoord)aY
- {
- offset.x = aX;
- offset.y = aY;
- return self;
- }
-
- - (NXCoord)width
- {
- return width;
- }
-
- - (NXCoord)height
- {
- return height;
- }
-
- - (Polygon *)contour
- {
- return &contour;
- }
-
- - layout
- {
- Tree *c;
-
- if(!updateLayout)
- return nil;
- if(zipped){
- [self layoutLeaf];
- updateLayout = NO;
- return self;
- }
- for(c = child;c;c = [c sibling])
- [c layout];
- if(child)
- [self attachParent:[self join]];
- else
- [self layoutLeaf];
- updateLayout = NO;
- return self;
- }
-
- - getTextFrame:(NXRect *)aRect
- {
- NXSetRect(aRect, pos.x, pos.y + deltaText.y, width, textCellFrame.size.height);
- return self;
- }
-
- //************************************************************************
- // tree data structure manipulation
-
- - sibling
- {
- return sibling;
- }
-
- - child
- {
- return child;
- }
-
- - parent
- {
- return parent;
- }
-
- - addTree:(Tree *)aTree
- {
- Tree *dummy;
- id undoManager;
-
- aTree->parent = self;
- aTree->linkKind = linkKind;
- aTree->biegFactor = biegFactor;
- aTree->parentDistance = parentDistance;
- aTree->shadow = shadow;
- aTree->shadowColor = shadowColor;
- aTree->border = border;
- if(!child){
- child = aTree;
- } else {
- dummy = child;
- while(dummy->sibling)
- dummy = dummy->sibling;
- dummy->sibling = aTree;
- aTree->sibling = nil;
- }
- [self setUpdateLayout:YES];
- if(delegate){
- undoManager = [delegate undoManager];
- [undoManager setUndoName:"Addition"];
- [undoManager setRedoName:"Deletion"];
- [[undoManager setUndoTarget:self] removeChild:aTree];
- [delegate declareSelection:aTree];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_ALL | SCROLL_TREEVIEW)];
- }
- return self;
- }
-
- - removeChild:(Tree *)aChild
- {
- Tree *dummy;
- id undoManager;
- int i;
-
- if(!child || !aChild)
- return self;
- [self setUpdateLayout:YES];
- dummy = child;
- i = 0;
- if(dummy == aChild)
- child = aChild->sibling;
- else {
- while(dummy->sibling && dummy->sibling != aChild){
- dummy = dummy->sibling;
- i++;
- }
- if(dummy->sibling == aChild)
- dummy->sibling = aChild->sibling;
- }
- aChild->parent = nil;
- aChild->sibling = nil;
- if(delegate){
- [delegate declareSelection:nil];
- undoManager = [delegate undoManager];
- [undoManager freeUndoArgsOnRecordDiscard];
- [undoManager setUndoName:"Deletion"];
- [undoManager setRedoName:"Addition"];
- [[undoManager setUndoTarget:self] insertTree:aChild at:i];
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_ALL];
- } else
- [aChild free];
- return self;
- }
-
- - insertTree:(Tree *)aTree at:(int)aPos
- {
- Tree *dummy;
- id undoManager;
- int i;
-
- aTree->parent = self;
- aTree->linkKind = linkKind;
- aTree->biegFactor = biegFactor;
- aTree->parentDistance = parentDistance;
- aTree->shadow = shadow;
- aTree->shadowColor = shadowColor;
- aTree->border = border;
- if(!child){
- child = aTree;
- } else {
- dummy = child;
- i = 0;
- while(dummy->sibling && i < aPos)
- dummy = dummy->sibling;
- aTree->sibling = dummy->sibling;
- dummy->sibling = aTree;
- }
- [self setUpdateLayout:YES];
- if(delegate){
- undoManager = [delegate undoManager];
- [undoManager setUndoName:"Addition"];
- [undoManager setRedoName:"Deletion"];
- [[undoManager setUndoTarget:self] removeChild:aTree];
- [delegate declareSelection:aTree];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_ALL | SCROLL_TREEVIEW)];
- }
- return self;
- }
-
-
- //************************************************************************
- // properties
-
- - attachFile:(const char *)aFileName
- {
- NXRect r;
- BOOL attachUpdate = YES;
-
- if(verknuepfung){
- [verknuepfung free];
- attachUpdate = NO;
- }
- verknuepfung = [[NXDataLink allocFromZone:[self zone]] initLinkedToFile:aFileName];
- if(attachUpdate){
- hasVerknuepfung = YES;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- }
- return self;
- }
-
- - breakAttachment
- {
- NXRect r;
-
- if(!hasVerknuepfung)
- return self;
- [self getBounds:&r];
- hasVerknuepfung = NO;
- [verknuepfung free];
- verknuepfung = nil;
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (BOOL)attached
- {
- return hasVerknuepfung;
- }
-
- - attachSound:(const char *)aSoundName
- {
- NXRect r;
- BOOL soundUpdate = YES;
-
- if(geraeusch){
- [geraeusch free];
- soundUpdate = NO;
- }
- geraeusch = [[Sound allocFromZone:[self zone]] initFromSoundfile:aSoundName];
- if(soundUpdate){
- hasSound = YES;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- }
- return self;
- }
-
- - breakSound
- {
- NXRect r;
-
- if(!hasSound)
- return self;
- [self getBounds:&r];
- hasSound = NO;
- [geraeusch free];
- geraeusch = nil;
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (BOOL)hasSound
- {
- return hasSound;
- }
-
- - attachedSound
- {
- return geraeusch;
- }
-
- - setSound:aSound
- {
- NXRect r;
- BOOL soundUpdate = YES;
-
- if(geraeusch){
- [geraeusch free];
- soundUpdate = NO;
- }
- geraeusch = aSound;
- if(soundUpdate){
- hasSound = YES;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- }
- return self;
- }
-
- - applyStyleToSubtree
- {
- Properties props;
-
- if(child){
- [self getProps:&props];
- [child promoteProps:&props];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- }
- return self;
- }
-
- - promoteProps:(Properties *)aProps
- {
- outline = aProps->outline;
- if([textCell font] != aProps->font){
- [textCell setFont:aProps->font];
- [self changeText];
- [self setUpdateLayout:YES];
- }
- if(pathKind != aProps->pathKind){
- [gpath resetFill];
- pathKind = aProps->pathKind;
- [self makePath];
- [self setUpdateLayout:YES];
- }
- fillColor = aProps->fillColor;
- outlineColor = aProps->outlineColor;
- [textCell setTextColor:aProps->textColor];
- linewidth = aProps->linewidth;
- if(ending != aProps->ending){
- ending = aProps->ending;
- }
- if(parentEnding != aProps->parentEnding){
- parentEnding = aProps->parentEnding;
- }
- if(sibling)
- [sibling promoteProps:aProps];
- if(child)
- [child promoteProps:aProps];
- return self;
- }
-
- - getProps:(Properties *)aProps
- {
- aProps->outline = outline;
- aProps->font = [textCell font];
- aProps->pathKind = pathKind;
- aProps->fillColor = fillColor;
- aProps->outlineColor = outlineColor;
- aProps->textColor = [textCell textColor];
- aProps->linewidth = linewidth;
- aProps->ending = ending;
- aProps->parentEnding = parentEnding;
- return self;
- }
-
- - changeTo:(Properties *)aProps
- {
- NXRect r, dummyRect, pr;
- BOOL checkResize, makeUnion;
-
- [self getBounds:&r];
- checkResize = NO;
- makeUnion = NO;
- outline = aProps->outline;
- if([textCell font] != aProps->font){
- [textCell setFont:aProps->font];
- [self changeText];
- [self setUpdateLayout:YES];
- checkResize = YES;
- }
- if(pathKind != aProps->pathKind){
- [gpath resetFill];
- pathKind = aProps->pathKind;
- [self makePath];
- [self setUpdateLayout:YES];
- checkResize = YES;
- }
- fillColor = aProps->fillColor;
- outlineColor = aProps->outlineColor;
- [textCell setTextColor:aProps->textColor];
- if(ending != aProps->ending){
- ending = aProps->ending;
- makeUnion = YES;
- }
- if(parentEnding != aProps->parentEnding){
- parentEnding = aProps->parentEnding;
- if(parent){
- [parent getBounds:&pr];
- [delegate updateViewsDirty:YES rect:&pr flag:UPDATE_TREEVIEW];
- }
- }
- if(aProps->linewidth != linewidth){
- linewidth = aProps->linewidth;
- makeUnion = YES;
- }
- if(makeUnion){
- [self getBounds:&dummyRect];
- NXUnionRect(&dummyRect, &r);
- }
- if(checkResize)
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- else
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- //************************************************************************
- // tree properties
-
- - (NXCoord)border
- {
- return border;
- }
-
- - setBorder:(NXCoord)aBorder
- {
- border = aBorder;
- [self setUpdateLayout:YES];
- if(child)
- [child setBorder:aBorder];
- if(sibling)
- [sibling setBorder:aBorder];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (NXCoord)parentDistance
- {
- return parentDistance;
- }
-
- - setParentDistance:(NXCoord)aParentDistance
- {
- parentDistance = aParentDistance;
- [self setUpdateLayout:YES];
- if(child)
- [child setParentDistance:aParentDistance];
- if(sibling)
- [sibling setParentDistance:aParentDistance];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (BOOL)shadow
- {
- return shadow;
- }
-
- - setShadow:(BOOL)aShadow
- {
- shadow = aShadow;
- if(child)
- [child setShadow:aShadow];
- if(sibling)
- [sibling setShadow:aShadow];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (NXColor)shadowColor
- {
- return shadowColor;
- }
-
- - setShadowColor:(NXColor)aColor
- {
- shadowColor = aColor;
- if(child)
- [child setShadowColor:aColor];
- if(sibling)
- [sibling setShadowColor:aColor];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (int)linkKind
- {
- return linkKind;
- }
-
- - setLinkKind:(int)aLinkKind
- {
- linkKind = aLinkKind;
- if(child)
- [child setLinkKind:aLinkKind];
- if(sibling)
- [sibling setLinkKind:aLinkKind];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - changeLinkKind
- {
- linkKind = (linkKind + 1) % 2;
- if(child)
- [child changeLinkKind];
- if(sibling)
- [sibling changeLinkKind];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (float)biegFactor
- {
- return biegFactor;
- }
-
- - setBiegFactor:(float)aBiegFactor
- {
- biegFactor = aBiegFactor;
- if(child)
- [child setBiegFactor:aBiegFactor];
- if(sibling)
- [sibling setBiegFactor:aBiegFactor];
- if(!parent)
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TREEVIEW];
- return self;
- }
-
- //************************************************************************
- // node properties
-
- - (const char *)label
- {
- return [textCell stringValue];
- }
-
- - setLabel:(const char *)aLabel
- {
- [textCell setStringValue:aLabel];
- [self changeText];
- [self setUpdateLayout:YES];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - setRTFDescription:(const char *)aDescription
- {
- [nodeDescription setRTF:aDescription];
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TEXTVIEW];
- return self;
- }
-
- - setDescription:(const char *)aDescription
- {
- [nodeDescription setAscii:aDescription];
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_TEXTVIEW];
- return self;
- }
-
- - changeDescriptionFrom:aTextView
- {
- [nodeDescription setRTFFromTextView:aTextView];
- [delegate updateViewsDirty:YES rect:NULL flag:UPDATE_NONE];
- return self;
- }
-
- - putDescriptionIn:aTextView
- {
- [aTextView replaceSelWithRichText:[nodeDescription stream]];
- [nodeDescription freeStream];
- return self;
- }
-
- - (int)pathKind
- {
- return pathKind;
- }
-
- - setPathKind:(int)aPathKind
- {
- [gpath resetFill];
- pathKind = aPathKind;
- [self makePath];
- [self setUpdateLayout:YES];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (BOOL)outline
- {
- return outline;
- }
-
- - setOutline:(BOOL)aOutline
- {
- NXRect r;
-
- outline = aOutline;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - font
- {
- return [textCell font];
- }
-
- - changeFont:sender
- {
- [textCell setFont:[sender convertFont:[textCell font]]];
- [self changeText];
- [self setUpdateLayout:YES];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (NXColor)fillColor
- {
- return fillColor;
- }
-
- - setFillColor:(NXColor)aColor
- {
- NXRect r;
-
- fillColor = aColor;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (NXColor)outlineColor
- {
- return outlineColor;
- }
-
- - setOutlineColor:(NXColor)aColor
- {
- NXRect r;
-
- outlineColor = aColor;
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (NXColor)textColor
- {
- return [textCell textColor];
- }
-
- - setTextColor:(NXColor)aColor
- {
- NXRect r;
-
- [textCell setTextColor:aColor];
- [self getBounds:&r];
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (float)linewidth
- {
- return linewidth;
- }
-
- - setLinewidth:(float)aLinewidth
- {
- NXRect r;
-
- if(aLinewidth > linewidth){
- linewidth = aLinewidth;
- [self getBounds:&r];
- } else {
- [self getBounds:&r];
- linewidth = aLinewidth;
- }
- [delegate updateViewsDirty:YES rect:&r flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (BOOL)zipped
- {
- return zipped;
- }
-
- - changeZipped
- {
- zipped = ! zipped;
- [self setUpdateLayout:YES];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- - (int)ending
- {
- return ending;
- }
-
- - setEnding:(int)aEnding
- {
- NXRect r,br;
-
- [self getBounds:&br];
- ending = aEnding;
- [self getBounds:&r];
- NXUnionRect(&br,&r);
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- - (int)parentEnding;
- {
- return parentEnding;
- }
-
- - setParentEnding:(int)aEnding
- {
- NXRect r,br;
-
- [self getBounds:&br];
- parentEnding = aEnding;
- [self getBounds:&r];
- NXUnionRect(&br,&r);
- [delegate updateViewsDirty:YES rect:&r flag:UPDATE_TREEVIEW];
- return self;
- }
-
- //************************************************************************
- // misc
-
- - (BOOL)selected
- {
- return selected;
- }
-
- - setSelected:(BOOL)aBOOL
- {
- selected = aBOOL;
- return self;
- }
-
- - setUpdateLayout:(BOOL)aBool
- {
- Tree *dummy;
-
- updateLayout = aBool;
- if(aBool)
- if(parent){
- [parent setUpdateLayout:YES];
- dummy = [parent child];
- dummy->updateLayout = YES;
- while([dummy sibling]){
- dummy = [dummy sibling];
- dummy->updateLayout = YES;
- }
- }
- return self;
- }
-
- - positionFrom:(const NXPoint *)aPoint
- {
- pos.x = aPoint->x + offset.x;
- pos.y = aPoint->y + offset.y;
- [self changePos];
- if(child)
- [child positionFrom:&pos];
- if(sibling)
- [sibling positionFrom:&pos];
- return self;
- }
-
- - setPositionTo:(const NXPoint *)aPoint
- {
- pos.x = aPoint->x;
- pos.y = aPoint->y;
- [self changePos];
- if(child)
- [child positionFrom:&pos];
- if(sibling)
- [sibling positionFrom:&pos];
- return self;
- }
-
- - linkPoint:(NXPoint *)aPoint
- {
- aPoint->x = pos.x + deltaLink.x;
- aPoint->y = pos.y + deltaLink.y;
- return self;
- }
-
- - linkParentPoint:(NXPoint *)aPoint
- {
- aPoint->x = pos.x + width + (parentDistance + border) * (1 - biegFactor) / 2;
- aPoint->y = pos.y + deltaLink.y;
- return self;
- }
-
- - linkChildPoint:(NXPoint *)aPoint
- {
- aPoint->x = pos.x - (parentDistance + border) * (1 - biegFactor) / 2;
- aPoint->y = pos.y + deltaLink.y;
- return self;
- }
-
- - delegate
- {
- return delegate;
- }
-
- - setDelegate:aDelegate
- {
- id oldDelegate;
-
- oldDelegate = delegate;
- delegate = aDelegate;
- return oldDelegate;
- }
-
- - setDelegateRecursive:aDelegate
- {
- delegate = aDelegate;
- if(child)
- [child setDelegateRecursive:aDelegate];
- if(sibling)
- [sibling setDelegateRecursive:aDelegate];
- return self;
- }
-
- - textDidEnd:textObject endChar:(unsigned short)endChar
- {
- int maxlen,length;
- char *buffer;
- NXStream *stream;
-
- [textObject removeFromSuperview];
- [textObject setDelegate:nil];
- [textObject setSel:0 :0];
- if([textObject textLength]){
- stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
- [textObject writeText:stream];
- NXGetMemoryBuffer(stream, &buffer, &length, &maxlen);
- [textCell setStringValue:buffer];
- NXCloseMemory(stream, NX_FREEBUFFER);
- }
- [self changeText];
- [self setUpdateLayout:YES];
- [delegate updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
- return self;
- }
-
- //*************************************************************************
- // streaming to diagram2 format
-
-
- - (unsigned)dgSymbolNr
- {
- return dgSymbolNr;
- }
-
- - dgWriteSymbol:(NXStream *)stream buffer:(char *)buffer filename:(const char *)aName
- {
- id font;
- char rtfItalic[3], rtfBold[3];
- unsigned i;
- int err;
-
- dgSymbolNr = [Tree dgNextNr];
- sprintf(buffer,"symbol %d\n", dgSymbolNr);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tshape \"%s\"\n", dgShapeSymbolName[pathKind]);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tlocation %.2f %.2f\n",pos.x,pos.y);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tsize %.2f %.2f\n",width,height);
- NXWrite(stream,buffer,strlen(buffer));
- if(outline)
- NXWrite(stream,"\tframed\n", 8);
- if(fill)
- NXWrite(stream,"\tfilled\n", 8);
- if(shadow)
- NXWrite(stream,"\tshadowed\n", 10);
- if(outline){
- i = 0;
- while(i < [dgColorList colorCount] &&
- !NXEqualColor(outlineColor,[dgColorList colorNamed:[dgColorList nameOfColorAt:i]]))
- i++;
- if(i == [dgColorList colorCount]){
- sprintf(buffer,"woodColorIndexed%d",i);
- [dgColorList setColorNamed:buffer color:outlineColor];
- }
- sprintf(buffer,"\tframeColor colorIndex %d\n",i);
- NXWrite(stream,buffer,strlen(buffer));
- }
- if(fill){
- i = 0;
- while(i < [dgColorList colorCount] &&
- !NXEqualColor(fillColor,[dgColorList colorNamed:[dgColorList nameOfColorAt:i]]))
- i++;
- if(i == [dgColorList colorCount]){
- sprintf(buffer,"woodColorIndexed%d",i);
- [dgColorList setColorNamed:buffer color:fillColor];
- }
- sprintf(buffer,"\tfillColor colorIndex %d\n",i);
- NXWrite(stream,buffer,strlen(buffer));
- }
- if(shadow){
- i = 0;
- while(i < [dgColorList colorCount] &&
- !NXEqualColor(shadowColor,[dgColorList colorNamed:[dgColorList nameOfColorAt:i]]))
- i++;
- if(i == [dgColorList colorCount]){
- sprintf(buffer,"woodColorIndexed%d",i);
- [dgColorList setColorNamed:buffer color:shadowColor];
- }
- sprintf(buffer,"\tshadowColor colorIndex %d\n",i);
- NXWrite(stream,buffer,strlen(buffer));
- }
- sprintf(buffer,"\tlineWidth %.2f\n",linewidth);
- NXWrite(stream,buffer,strlen(buffer));
- if(hasVerknuepfung){
- sprintf(buffer,"\tattachment \"%s\"\n",[verknuepfung sourceFilename]);
- NXWrite(stream,buffer,strlen(buffer));
- }
- if(hasSound){
- sprintf(buffer,"%s/Sound%d.snd",aName,dgSymbolNr);
- err = [geraeusch writeSoundfile:buffer];
- if(err)
- NXRunAlertPanel("Save Sound","Cannot write %s","OK",NULL,NULL,buffer);
- else {
- sprintf(buffer,"\tsoundFile \"Sound%d.snd\"\n",dgSymbolNr);
- NXWrite(stream,buffer,strlen(buffer));
- }
- }
- font = [textCell font];
- if(strstr([font displayName], "Bold"))
- strcpy(rtfBold,"b");
- else
- strcpy(rtfBold,"b0");
- if(strstr([font displayName], "Italic") || strstr([font displayName], "Oblique"))
- strcpy(rtfItalic,"i");
- else
- strcpy(rtfItalic,"i0");
- sprintf(buffer, dgRtfControlName, [font familyName], rtfBold, rtfItalic, [font pointSize] * 2, [textCell stringValue]);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,"\n",1);
- NXWrite(stream,"\ttextPlacement middle\n", 22);
- NXWrite(stream,dgEndName, strlen(dgEndName));
- if(child)
- [child dgWriteSymbol:stream buffer:buffer filename:aName];
- if(sibling)
- [sibling dgWriteSymbol:stream buffer:buffer filename:aName];
- return self;
- }
-
- - dgWriteVertex:(NXStream *)stream buffer:(char *)buffer
- {
- NXPoint p2,p3;
-
- if(parent){
- dgVertexNr[0] = [Tree dgNextNr];
- sprintf(buffer,"vertex %d\n",dgVertexNr[0]);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,dgEndName, strlen(dgEndName));
- dgVertexNr[1] = [Tree dgNextNr];
- sprintf(buffer,"vertex %d\n",dgVertexNr[1]);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,dgEndName, strlen(dgEndName));
- if(linkKind){
- [parent linkParentPoint:&p3];
- [self linkChildPoint:&p2];
- dgVertexNr[2] = [Tree dgNextNr];
- sprintf(buffer,"vertex %d\n",dgVertexNr[2]);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tlocation %.2f %.2f\n", p2.x, p2.y);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,dgEndName, strlen(dgEndName));
- dgVertexNr[3] = [Tree dgNextNr];
- sprintf(buffer,"vertex %d\n",dgVertexNr[3]);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tlocation %.2f %.2f\n", p3.x, p3.y);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,dgEndName, strlen(dgEndName));
- }
- }
- if(child)
- [child dgWriteVertex:stream buffer:buffer];
- if(sibling)
- [sibling dgWriteVertex:stream buffer:buffer];
- return self;
- }
-
- - dgWriteLine:(NXStream *)stream buffer:(char *)buffer
- {
- if(parent){
- sprintf(buffer,"line %d\n",[Tree dgNextNr]);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tfrom %d\n",dgSymbolNr);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\tto %d\n",[parent dgSymbolNr]);
- NXWrite(stream,buffer,strlen(buffer));
- if(ending != ENDING_NONE){
- switch(ending){
- case ENDING_ARROW:
- sprintf(buffer,"\ttailType arrow\n");
- break;
- case ENDING_HOLLOW:
- sprintf(buffer,"\ttailType hollowArrow\n");
- break;
- case ENDING_DOUBLE:
- sprintf(buffer,"\ttailType doubleArrow\n");
- break;
- case ENDING_SOLID:
- sprintf(buffer,"\ttailType solidCircle\n");
- break;
- case ENDING_CIRCLE:
- sprintf(buffer,"\ttailType circle\n");
- break;
- default:
- break;
- }
- NXWrite(stream,buffer,strlen(buffer));
- }
- if([parent parentEnding] != ENDING_NONE){
- switch([parent parentEnding]){
- case ENDING_ARROW:
- sprintf(buffer,"\theadType arrow\n");
- break;
- case ENDING_HOLLOW:
- sprintf(buffer,"\theadType hollowArrow\n");
- break;
- case ENDING_DOUBLE:
- sprintf(buffer,"\theadType doubleArrow\n");
- break;
- case ENDING_SOLID:
- sprintf(buffer,"\theadType solidCircle\n");
- break;
- case ENDING_CIRCLE:
- sprintf(buffer,"\theadType circle\n");
- break;
- default:
- break;
- }
- NXWrite(stream,buffer,strlen(buffer));
- }
- sprintf(buffer,"\t%d\n",dgVertexNr[0]);
- NXWrite(stream,buffer,strlen(buffer));
- if(linkKind){
- sprintf(buffer,"\t%d\n",dgVertexNr[2]);
- NXWrite(stream,buffer,strlen(buffer));
- sprintf(buffer,"\t%d\n",dgVertexNr[3]);
- NXWrite(stream,buffer,strlen(buffer));
- }
- sprintf(buffer,"\t%d\n",dgVertexNr[1]);
- NXWrite(stream,buffer,strlen(buffer));
- NXWrite(stream,dgEndName, strlen(dgEndName));
- }
- if(child)
- [child dgWriteLine:stream buffer:buffer];
- if(sibling)
- [sibling dgWriteLine:stream buffer:buffer];
- return self;
- }
-
- + saveToD2Tree:aTree fromView:aView toFile:(const char *)aFile printInfo:aPrintInfo
- {
- NXStream *stream;
- NXTypedStream *typedStream;
- char fileNameBuffer[MAXPATHLEN],commandBuffer[MAXPATHLEN + 20];
- char buffer[1024];
- NXRect dummyRect;
-
- dgColorList = [[NXColorList alloc] init];
- [aView getBounds:&dummyRect];
- dgNextNr = 0;
- stream = NXOpenMemory(NULL,0,NX_WRITEONLY);
- NXWrite(stream, dgDocuBegin,strlen(dgDocuBegin));
- strcpy(fileNameBuffer,aFile);
- sprintf(commandBuffer,"mkdir %s",fileNameBuffer);
- system(commandBuffer);
- if(aTree){
- NXWrite(stream, dgSymbolComment,strlen(dgSymbolComment));
- [aTree dgWriteSymbol:stream buffer:buffer filename:aFile];
- NXWrite(stream, dgVertexComment,strlen(dgVertexComment));
- [aTree dgWriteVertex:stream buffer:buffer];
- NXWrite(stream, dgLineComment,strlen(dgLineComment));
- [aTree dgWriteLine:stream buffer:buffer];
- }
- strcpy(fileNameBuffer,aFile);
- strcat(fileNameBuffer,"/DiagramText");
- NXSaveToFile(stream, fileNameBuffer);
- NXCloseMemory(stream,NX_FREEBUFFER);
- strcpy(fileNameBuffer,aFile);
- strcat(fileNameBuffer,"/PrintInfo");
- stream = NXOpenMemory(NULL,0,NX_WRITEONLY);
- typedStream = NXOpenTypedStream(stream,NX_WRITEONLY);
- NXWriteRootObject(typedStream,aPrintInfo);
- NXCloseTypedStream(typedStream);
- NXSeek(stream, - 1, NX_FROMCURRENT);
- NXWrite(stream,dgPrintInfoEnd,6);
- NXSaveToFile(stream, fileNameBuffer);
- NXCloseMemory(stream,NX_FREEBUFFER);
- strcpy(fileNameBuffer,aFile);
- strcat(fileNameBuffer,"/Colors.clr");
- [dgColorList saveTo:fileNameBuffer];
- [dgColorList free];
- dgColorList = nil;
- return self;
- }
-
- + (unsigned)dgNextNr
- {
- dgNextNr++;
- return dgNextNr;
- }
-
- //*************************************************************************
- // streaming
-
- - writeStyleToPBStream:(NXTypedStream *)stream
- {
- NXWriteTypes(stream,"iiiif",&outline,&pathKind,&ending,&parentEnding,&linewidth);
- NXWriteColor(stream,fillColor);
- NXWriteColor(stream,outlineColor);
- NXWriteColor(stream,[textCell textColor]);
- NXWriteObject(stream,[textCell font]);
- return self;
- }
-
- - readStyleFromPBStream:(NXTypedStream *)stream
- {
- Properties props;
-
- NXReadTypes(stream,"iiiif",&(props.outline),&(props.pathKind),&(props.ending),&(props.parentEnding),&(props.linewidth));
- props.fillColor = NXReadColor(stream);
- props.outlineColor = NXReadColor(stream);
- props.textColor = NXReadColor(stream);
- props.font = NXReadObject(stream);
- [self changeTo:&props];
- return self;
- }
-
- - writeToPBStream:(NXTypedStream *)stream
- {
- Tree *tmpParent, *tmpSibling;
-
- tmpParent = parent;
- tmpSibling = sibling;
- parent = sibling = nil;
- NXWriteRootObject(stream, self);
- parent = tmpParent;
- sibling = tmpSibling;
- return self;
- }
-
- - writeToMMAPB:(NXStream *)stream
- {
- if(child){
- NXWrite(stream,"{",1);
- NXWrite(stream,[textCell stringValue],strlen([textCell stringValue]));
- NXWrite(stream,", ",2);
- [child writeToMMAPB:stream];
- NXWrite(stream,"}",1);
- } else {
- NXWrite(stream,[textCell stringValue],strlen([textCell stringValue]));
- }
- if(sibling){
- NXWrite(stream,", ",2);
- [sibling writeToMMAPB:stream];
- }
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- //BOOL hasChild,hasSibling;
- int hasChild,hasSibling;
- id retval;
-
- NX_DURING
- [super write:stream];
- hasChild = (child ? YES : NO);
- hasSibling = (sibling ? YES :NO);
- NXWriteTypes(stream,"ii",&hasVerknuepfung,&hasSound);
- NXWriteTypes(stream,"iiff",&hasChild,&hasSibling,&parentDistance,&border);
- NXWriteTypes(stream,"iiiiiff",&zipped,&shadow,&outline,&pathKind,&linkKind,&linewidth,&biegFactor);
- NXWriteTypes(stream,"ii",&ending,&parentEnding);
- NXWriteColor(stream,fillColor);
- NXWriteColor(stream,outlineColor);
- NXWriteColor(stream,shadowColor);
- NXWriteObject(stream,textCell);
- NXWriteObject(stream,nodeDescription);
- NXWriteObjectReference(stream, parent);
- if(hasChild)
- NXWriteObject(stream, child);
- if(hasSibling)
- NXWriteObject(stream, sibling);
- if(hasVerknuepfung)
- NXWriteObject(stream,verknuepfung);
- if(hasSound)
- NXWriteObject(stream,geraeusch);
- retval = self;
- NX_HANDLER
- retval = nil;
- NX_ENDHANDLER
- return retval;
- }
-
- - read:(NXTypedStream *)stream
- {
- //BOOL hasChild,hasSibling;
- int hasChild,hasSibling;
- id retval;
-
- NX_DURING
- NXSetTypedStreamZone(stream, [self zone]);
- [super read:stream];
- NXReadTypes(stream,"ii",&hasVerknuepfung,&hasSound);
- NXReadTypes(stream,"iiff", &hasChild,&hasSibling,&parentDistance,&border);
- if(NXTypedStreamClassVersion(stream, "Tree") == [Tree version])
- NXReadTypes(stream,"iiiiiff",&zipped,&shadow,&outline,&pathKind,&linkKind,&linewidth,&biegFactor);
- else {
- NXReadTypes(stream,"iiiiif",&zipped,&shadow,&outline,&pathKind,&linkKind,&linewidth);
- biegFactor = 0.33;
- }
- NXReadTypes(stream,"ii",&ending,&parentEnding);
- fillColor = NXReadColor(stream);
- outlineColor = NXReadColor(stream);
- shadowColor = NXReadColor(stream);
- textCell = NXReadObject(stream);
- nodeDescription = NXReadObject(stream);
- parent = NXReadObject(stream);
- if(hasChild)
- child = NXReadObject(stream);
- else
- child = nil;
- if(hasSibling)
- sibling = NXReadObject(stream);
- else
- sibling = nil;
- if(hasVerknuepfung)
- verknuepfung = NXReadObject(stream);
- if(hasSound)
- geraeusch = NXReadObject(stream);
- retval = self;
- NX_HANDLER
- retval = nil;
- NX_ENDHANDLER
- return retval;
- }
-
- - awake
- {
- [super awake];
- contour.lower.head = contour.upper.head = NULL;
- contour.lower.tail = contour.upper.tail = NULL;
- offset.x = offset.y = 0.0;
- pos.x = pos.y = 0.0;
- gpath = [[UPath allocFromZone:[self zone]] init];
- deltaShadow.x = deltaShadow.y = 3;
- placer.rect[0] = placer.rect[1] = 6;
- placer.roundRect[0] = placer.roundRect[1] = 6;
- placer.roundRect[2] = 3;
- placer.ellipse[0] = 6;
- placer.ellipse[1] = 4;
- placer.rhomb[0] = 12;
- placer.rhomb[1] = 3;
- placer.hexagon[0] = 6;
- placer.hexagon[1] = 6;
- placer.hexagon[2] = 1;
- [self makePath];
- selected = NO;
- updateLayout = YES;
- delegate = nil;
- fill = YES;
- return self;
- }
-
- //*************************************************************************
- // SearchableText support
-
- - searchTreeFor:(const char *)pattern untilNode:endNode
- reverse:(BOOL)rev regexpr:(BOOL)regexpr cases:(BOOL)cases position:(int *)positionS size:(int *)sizeS
- {
- MiscString *labelS;
- id result;
- int resultPos;
-
- result = nil;
- resultPos = -1;
- labelS = [[MiscString alloc] initString:[self label]];
- if(regexpr)
- resultPos = [labelS spotOfRegex:pattern caseSensitive:cases length:sizeS];
- else
- resultPos = [labelS spotOfStr:pattern caseSensitive:cases];
- if(resultPos > -1){
- *positionS = resultPos;
- if(!regexpr)
- *sizeS = strlen(pattern);
- result = self;
- } else if(self == endNode)
- return nil;
- else {
- if(rev)
- result = [[self previousInDepth] searchTreeFor:pattern untilNode:endNode
- reverse:rev regexpr:regexpr cases:cases position:positionS size:sizeS];
- else
- result = [[self nextInDepth] searchTreeFor:pattern untilNode:endNode
- reverse:rev regexpr:regexpr cases:cases position:positionS size:sizeS];
- }
- [labelS free];
- return result;
- }
-
- - replaceTreeFor:(const char *)pattern with:(const char *)replacement untilNode:endNode
- regexpr:(BOOL)regexpr cases:(BOOL)cases result:(int *)result
- {
- MiscString *labelS;
- int nr;
-
- nr = 0;
- labelS = [[MiscString alloc] initString:[self label]];
- if(regexpr)
- nr = [labelS replaceEveryOccurrenceOfRegex:pattern with:replacement caseSensitive:cases];
- else
- nr = [labelS replaceEveryOccurrenceOf:pattern with:replacement caseSensitive:cases];
- if(nr > 0){
- [textCell setStringValue:[labelS stringValue]];
- [self changeText];
- [self setUpdateLayout:YES];
- }
- *result += nr;
- if(self != endNode)
- [[self nextInDepth] replaceTreeFor:pattern with:replacement untilNode:endNode
- regexpr:regexpr cases:cases result:result];
- [labelS free];
- return self;
- }
-
- - nextInDepth
- {
- Tree *r, *t;
-
- if(child)
- r = child;
- else if(sibling)
- r = sibling;
- else {
- t = self;
- while([t parent] && ![t sibling])
- t = [t parent];
- if([t sibling])
- r = [t sibling];
- else
- r = t;
- }
- return r;
- }
-
- - previousInDepth
- {
- Tree *r, *t;
-
- if(!parent)
- return [self lastInDepth];
- if([parent child] == self)
- return parent;
- else {
- r = [parent child];
- t = [r sibling];
- while(t != self){
- r = t;
- t = [t sibling];
- }
- return [r lastInDepth];
- }
- }
-
- - lastInDepth
- {
- Tree *r, *t;
-
- r = self;
- t = child;
- while(t){
- r = t;
- while(t){
- r = t;
- t = [t sibling];
- }
- t = [r child];
- }
- return r;
- }
-
- - (BOOL)replaceLabelSelectionWith:(const char *)replacement pos:(int)aPos size:(int)aSize
- {
- MiscString *labelS, *pattern;
- int nr;
- BOOL result = NO;
-
- labelS = [[MiscString alloc] initString:[self label]];
- if(aPos + aSize > [labelS length])
- return result;
- pattern = [labelS midFrom:aPos to:(aPos + aSize - 1) fromZone:[self zone]];
- nr = [labelS replaceEveryOccurrenceOfString:pattern with:replacement caseSensitive:YES];
- if(nr > 0){
- [textCell setStringValue:[labelS stringValue]];
- [self changeText];
- [self setUpdateLayout:YES];
- result = YES;
- }
- [labelS free];
- return result;
- }
-
- @end
-
- @implementation Tree(PrivateMethods)
-
- - attachParent:(NXCoord)h
- {
- NXCoord x,y1,y2;
-
- x = border + parentDistance;
- y2 = (h - height) / 2 - border;
- y1 = y2 + height + 2 * border - h;
- [child setOffset:x + width :y1];
- contour.upper.head = allocLine(width,0,allocLine(x,y1,contour.upper.head,[self zone]),[self zone]);
- contour.lower.head = allocLine(width,0,allocLine(x,y2,contour.lower.head,[self zone]),[self zone]);
- return self;
- }
-
- - layoutLeaf
- {
- if(contour.lower.head)
- freePolyline(contour.lower.head);
- if(contour.upper.head)
- freePolyline(contour.upper.head);
- contour.upper.tail = allocLine(width + 2 * border,0,NULL,[self zone]);
- contour.upper.head = contour.upper.tail;
- contour.lower.tail = allocLine(0, - height - 2 * border,NULL,[self zone]);
- contour.lower.head = allocLine(width + 2 * border,0,contour.lower.tail,[self zone]);
- return self;
- }
-
- - (NXCoord)join
- {
- Tree *c;
- NXCoord d,h,sum;
- Polygon dummy;
-
- c = child;
- if(contour.lower.head)
- freePolyline(contour.lower.head);
- if(contour.upper.head)
- freePolyline(contour.upper.head);
- if(c->contour.upper.head)
- contour.upper.head = copyPolyline(c->contour.upper.head,&(contour.upper.tail),[self zone]);
- else
- contour.upper.head = contour.upper.tail = NULL;
- if(c->contour.lower.head)
- contour.lower.head = copyPolyline(c->contour.lower.head,&(contour.lower.tail),[self zone]);
- else
- contour.lower.head = contour.lower.tail = NULL;
- sum = h = [c height] + 2 * [c border];
- c = [c sibling];
- while(c) {
- if(c->contour.upper.head)
- dummy.upper.head = copyPolyline(c->contour.upper.head,&(dummy.upper.tail),[self zone]);
- else
- dummy.upper.head = dummy.upper.tail = NULL;
- if(c->contour.lower.head)
- dummy.lower.head = copyPolyline(c->contour.lower.head,&(dummy.lower.tail),[self zone]);
- else
- dummy.lower.head = dummy.lower.tail = NULL;
- d = merge(&contour,&dummy,[self zone]);
- [c setOffset:0 :d + h];
- h = [c height] + 2 * [c border];
- sum += d + h;
- c = [c sibling];
- }
- return sum;
- }
-
- - makePath
- {
- float r;
-
- [self calcWidthHeight];
- switch(pathKind){
- case RECT_NODETYPE:
- [gpath moveto:pos.x :pos.y];
- [gpath rlineto:width :0.0];
- [gpath rlineto:0.0 :height];
- [gpath rlineto:-width :0.0];
- [gpath rlineto:0.0 :-height];
- break;
- case ROUNDRECT_NODETYPE:
- r = MIN(width / 3, height / 3);
- [gpath moveto:pos.x :pos.y + r];
- [gpath lineto:pos.x :pos.y + height - r];
- [gpath curveto:pos.x :pos.y + height - r + r * 0.5519
- :pos.x + r - r * 0.5519 :pos.y + height
- :pos.x + r :pos.y + height];
- [gpath lineto:pos.x + width - r :pos.y + height];
- [gpath curveto:pos.x + width - r + r * 0.5519 :pos.y + height
- :pos.x + width :pos.y + height - r + r * 0.5519
- :pos.x + width :pos.y + height - r];
- [gpath lineto:pos.x + width :pos.y + r];
- [gpath curveto:pos.x + width :pos.y + r - r * 0.5519
- :pos.x + width - r + r * 0.5519 :pos.y
- :pos.x + width - r :pos.y];
- [gpath lineto:pos.x + r :pos.y];
- [gpath curveto:pos.x + r - r * 0.5519 :pos.y
- :pos.x :pos.y + r - r * 0.5519
- :pos.x :pos.y + r];
- /* [gpath moveto:(pos.x + height / 3) :pos.y];
- [gpath arct:(pos.x + width) :pos.y :(pos.x + width) :(pos.y + height) :height / 3];
- [gpath arct:(pos.x + width) :(pos.y + height) :pos.x :(pos.y + height) :height / 3];
- [gpath arct:pos.x :(pos.y + height) :pos.x :pos.y : height / 3];
- [gpath arct:pos.x :pos.y :(pos.x + width) :pos.y :height / 3]; */
- break;
- case ELLIPSE_NODETYPE:
- [gpath moveto:(pos.x + width) :(pos.y + height / 2)];
- [gpath curveto:(pos.x + width) :(pos.y + height / 2 * 0.445)
- :(pos.x + width / 2 * 1.555) :pos.y
- :(pos.x + width / 2) :pos.y];
- [gpath curveto:(pos.x + width / 2 * 0.445) :pos.y
- :pos.x :(pos.y + height / 2 * 0.445)
- :pos.x :(pos.y + height / 2)];
- [gpath curveto:pos.x :(pos.y + height /2 * 1.555)
- :(pos.x + width / 2 * 0.445) :(pos.y + height)
- :(pos.x + width / 2) :(pos.y + height)];
- [gpath curveto:(pos.x + width / 2 * 1.555) :(pos.y + height)
- :(pos.x + width) :(pos.y + height / 2 * 1.555)
- :(pos.x + width) :(pos.y + height / 2)];
- break;
- case RHOMB_NODETYPE:
- [gpath moveto:pos.x + width / 2 :pos.y];
- [gpath rlineto:width / 2 :height / 2];
- [gpath rlineto:-width / 2 :height / 2];
- [gpath rlineto:-width / 2 :-height / 2];
- [gpath rlineto:width / 2 :-height / 2];
- break;
- case HEXAGON_NODETYPE:
- [gpath moveto:pos.x + placer.hexagon[0] :pos.y];
- [gpath rlineto:(width - 2 * placer.hexagon[0]) :0];
- [gpath rlineto:placer.hexagon[0] :height /2];
- [gpath rlineto:-placer.hexagon[0] :height /2];
- [gpath rlineto:(- width + 2 * placer.hexagon[0]) :0];
- [gpath rlineto:-placer.hexagon[0] :-height / 2];
- [gpath rlineto:placer.hexagon[0] :-height / 2];
- break;
- default:
- break;
- }
- return self;
- }
-
- - changeText
- {
- [self calcWidthHeight];
- [self fillGPathParams];
- gpath->bbox[2] = gpath->bbox[0] + width;
- gpath->bbox[3] = gpath->bbox[1] + height;
- return self;
- }
-
- - changePos
- {
- NXPoint delta;
-
- [self fillGPathParams];
- switch(pathKind){
- case RECT_NODETYPE:
- delta.x = gpath->params[0] - gpath->bbox[0];
- delta.y = gpath->params[1] - gpath->bbox[1];
- break;
- case ROUNDRECT_NODETYPE:
- delta.x = gpath->params[0] - gpath->bbox[0];
- delta.y = gpath->params[23] - gpath->bbox[1];
- break;
- case ELLIPSE_NODETYPE:
- delta.x = gpath->params[10] - gpath->bbox[0];
- delta.y = gpath->params[5] - gpath->bbox[1];
- break;
- case RHOMB_NODETYPE:
- delta.x = gpath->params[0] - gpath->bbox[0] - width / 2;
- delta.y = gpath->params[1] - gpath->bbox[1];
- break;
- case HEXAGON_NODETYPE:
- delta.x = gpath->params[0] - gpath->bbox[0] - placer.hexagon[0];
- delta.y = gpath->params[1] - gpath->bbox[1];
- break;
- default:
- break;
- }
- gpath->bbox[0] += delta.x;
- gpath->bbox[1] += delta.y;
- gpath->bbox[2] += delta.x;
- gpath->bbox[3] += delta.y;
- return self;
- }
-
- - fillGPathParams
- {
- float r;
-
- switch(pathKind){
- case RECT_NODETYPE:
- gpath->params[0] = pos.x;
- gpath->params[1] = pos.y;
- gpath->params[2] = width;
- gpath->params[3] = 0.0;
- gpath->params[4] = 0.0;
- gpath->params[5] = height;
- gpath->params[6] = -width;
- gpath->params[7] = 0.0;
- gpath->params[8] = 0.0;
- gpath->params[9] = -height;
- break;
- case ROUNDRECT_NODETYPE:
- r = MIN(width / 3, height / 3);
- gpath->params[0] = pos.x;
- gpath->params[1] = pos.y + r;
- gpath->params[2] = pos.x;
- gpath->params[3] = pos.y + height - r;
- gpath->params[4] = pos.x;
- gpath->params[5] = pos.y + height - r + r * 0.5519;
- gpath->params[6] = pos.x + r - r * 0.5519;
- gpath->params[7] = pos.y + height;
- gpath->params[8] = pos.x + r;
- gpath->params[9] = pos.y + height;
- gpath->params[10] = pos.x + width - r;
- gpath->params[11] = pos.y + height;
- gpath->params[12] = pos.x + width - r + r * 0.5519;
- gpath->params[13] = pos.y + height;
- gpath->params[14] = pos.x + width;
- gpath->params[15] = pos.y + height - r + r * 0.5519;
- gpath->params[16] = pos.x + width;
- gpath->params[17] = pos.y + height - r;
- gpath->params[18] = pos.x + width;
- gpath->params[19] = pos.y + r;
- gpath->params[20] = pos.x + width;
- gpath->params[21] = pos.y + r - r * 0.5519;
- gpath->params[22] = pos.x + width - r + r * 0.5519;
- gpath->params[23] = pos.y;
- gpath->params[24] = pos.x + width - r;
- gpath->params[25] = pos.y;
- gpath->params[26] = pos.x + r;
- gpath->params[27] = pos.y;
- gpath->params[28] = pos.x + r - r * 0.5519;
- gpath->params[29] = pos.y;
- gpath->params[30] = pos.x;
- gpath->params[31] = pos.y + r - r * 0.5519;
- gpath->params[32] = pos.x;
- gpath->params[33] = pos.y + r;
- /* gpath->params[0] = pos.x + height / 3;
- gpath->params[1] = pos.y;
- gpath->params[2] = pos.x + width;
- gpath->params[3] = pos.y;
- gpath->params[4] = pos.x + width;
- gpath->params[5] = pos.y + height;
- gpath->params[6] = height / 3;
- gpath->params[7] = pos.x + width;
- gpath->params[8] = pos.y + height;
- gpath->params[9] = pos.x;
- gpath->params[10] = pos.y + height;
- gpath->params[11] = height / 3;
- gpath->params[12] = pos.x;
- gpath->params[13] = pos.y + height;
- gpath->params[14] = pos.x;
- gpath->params[15] = pos.y;
- gpath->params[16] = height / 3;
- gpath->params[17] = pos.x;
- gpath->params[18] = pos.y;
- gpath->params[19] = pos.x + width;
- gpath->params[20] = pos.y;
- gpath->params[21] = height / 3; */
- break;
- case ELLIPSE_NODETYPE:
- gpath->params[0] = pos.x + width;
- gpath->params[1] = pos.y + height / 2;
- gpath->params[2] = pos.x + width;
- gpath->params[3] = pos.y + height / 2 * 0.445;
- gpath->params[4] = pos.x + width / 2 * 1.555;
- gpath->params[5] = pos.y;
- gpath->params[6] = pos.x + width / 2;
- gpath->params[7] = pos.y;
- gpath->params[8] = pos.x + width / 2 * 0.445;
- gpath->params[9] = pos.y;
- gpath->params[10] = pos.x;
- gpath->params[11] = pos.y + height / 2 * 0.445;
- gpath->params[12] = pos.x;
- gpath->params[13] = pos.y + height / 2;
- gpath->params[14] = pos.x;
- gpath->params[15] = pos.y + height /2 * 1.555;
- gpath->params[16] = pos.x + width / 2 * 0.445;
- gpath->params[17] = pos.y + height;
- gpath->params[18] = pos.x + width / 2;
- gpath->params[19] = pos.y + height;
- gpath->params[20] = pos.x + width / 2 * 1.555;
- gpath->params[21] = pos.y + height;
- gpath->params[22] = pos.x + width;
- gpath->params[23] = pos.y + height / 2 * 1.555;
- gpath->params[24] = pos.x + width;
- gpath->params[25] = pos.y + height / 2;
- break;
- case RHOMB_NODETYPE:
- gpath->params[0] = pos.x + width / 2;
- gpath->params[1] = pos.y;
- gpath->params[2] = width / 2;
- gpath->params[3] = height / 2;
- gpath->params[4] = -width / 2;
- gpath->params[5] = height / 2;
- gpath->params[6] = -width / 2;
- gpath->params[7] = -height / 2;
- gpath->params[8] =width / 2;
- gpath->params[9] = -height / 2;
- break;
- case HEXAGON_NODETYPE:
- gpath->params[0] = pos.x + placer.hexagon[0];
- gpath->params[1] = pos.y;
- gpath->params[2] = width - 2 * placer.hexagon[0];
- gpath->params[3] = 0;
- gpath->params[4] = placer.hexagon[0];
- gpath->params[5] = height / 2;
- gpath->params[6] = -placer.hexagon[0];
- gpath->params[7] = height / 2;
- gpath->params[8] =-width + 2 * placer.hexagon[0];
- gpath->params[9] = 0;
- gpath->params[10] =-placer.hexagon[0];
- gpath->params[11] = -height / 2;
- gpath->params[12] = placer.hexagon[0];
- gpath->params[13] = -height / 2;
- break;
- default:
- break;
- }
- return self;
- }
-
- - calcWidthHeight
- {
- NXCoord v1,v2;
- NXSize textSize;
-
- [textCell calcCellSize:&textSize];
- switch(pathKind){
- case RECT_NODETYPE:
- width = textSize.width + 2 * placer.rect[0];
- height = textSize.height + 2 * placer.rect[1];
- break;
- case ROUNDRECT_NODETYPE:
- width = textSize.width + 2 * placer.roundRect[0];
- height = textSize.height + 2 * placer.roundRect[1];
- break;
- case ELLIPSE_NODETYPE:
- height = textSize.height + 2 * placer.ellipse[0];
- v1 = placer.ellipse[0] - placer.ellipse[1];
- v2 = placer.ellipse[0] + height + placer.ellipse[1];
- width = (textSize.width / 2 + placer.ellipse[1]) * height / sqrt(v1 * v2);
- break;
- case RHOMB_NODETYPE:
- height = textSize.height + 2 * placer.rhomb[0];
- v1 = placer.rhomb[0] - placer.rhomb[1];
- width = (textSize.width / 2 + placer.rhomb[1]) * height / v1;
- break;
- case HEXAGON_NODETYPE:
- width = textSize.width + 2 * placer.hexagon[0];
- height = textSize.height + 2 * placer.hexagon[1];
- break;
- default:
- break;
- }
- deltaText.x = (width - textSize.width) / 2;
- deltaText.y = (height - textSize.height) / 2;
- deltaLink.x = width / 2;
- deltaLink.y = height / 2;
- NXSetRect(&textCellFrame, 0, 0, textSize.width, textSize.height);
- return self;
- }
-
- - internalCopyFromZone:(NXZone *)zone parent:aParent
- {
- Tree *theCopy;
-
- theCopy = [super copyFromZone:zone];
- theCopy->contour.upper.head = contour.upper.tail = NULL;
- theCopy->contour.lower.head = contour.lower.tail = NULL;
- theCopy->updateLayout = YES;
- theCopy->parent = aParent;
- if(child)
- theCopy->child = [child internalCopyFromZone:zone parent:theCopy];
- else
- theCopy->child = nil;
- if(sibling)
- theCopy->sibling = [sibling internalCopyFromZone:zone parent:aParent];
- else
- theCopy->sibling = nil;
- theCopy->selected = NO;
- theCopy->gpath = [gpath copyFromZone:zone];
- theCopy->nodeDescription = [nodeDescription copyFromZone:zone];;
- theCopy->delegate = nil;
- if(verknuepfung)
- theCopy->verknuepfung = [verknuepfung copyFromZone:zone];
- else
- theCopy->verknuepfung = nil;
- theCopy->textCell = [textCell copyFromZone:zone];
- return theCopy;
- }
-
- - calcIntersection:(NXPoint *)ip angle:(float *)alpha toPoint:(const NXPoint *)aPoint
- {
- NXPoint middle,l1,l2;
- float s,xm,ym,x0,y0,r,ausdruck,a,b;
-
- middle.x = pos.x + width / 2;
- middle.y = pos.y + height / 2;
- if(aPoint->y == middle.y){
- *alpha = 0;
- ip->y = middle.y;
- if(aPoint->x > middle.x)
- ip->x = pos.x + width;
- else
- ip->x = pos.x;
- return self;
- }
- if(aPoint->x == middle.x){
- ip->x = middle.x;
- if(aPoint->y > middle.y){
- ip->y = pos.y + height;
- *alpha = -90;
- } else {
- ip->y = pos.y;
- *alpha = 90;
- }
- return self;
- }
- s = (aPoint->y - middle.y) / (aPoint->x - middle.x);
- *alpha = 57.29577951 * atan(s);
- if(aPoint->y > middle.y){
- if(aPoint->x > middle.x){ // 4. quadrant
- switch(pathKind){
- case RECT_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y + height;
- l2.x = pos.x + width;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- case ROUNDRECT_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y + height;
- l2.x = pos.x + width - height / 3;
- l2.y = pos.y + height;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = l2.x = pos.x + width;
- l1.y = middle.y;
- l2.y = pos.y + height - height / 3;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- } else {
- r = height / 3;
- x0 = middle.x;
- y0 = middle.y;
- xm = pos.x + width - r;
- ym = pos.y + height - r;
- ausdruck = (pow(r,2) + pow(r,2)*pow(s,2) - pow(s,2)*pow(xm,2) +
- 2*pow(s,2)*xm*x0 - pow(s,2)*pow(x0,2) + 2*s*xm*ym - 2*s*x0*ym -
- pow(ym,2) - 2*s*xm*y0 + 2*s*x0*y0 + 2*ym*y0 - pow(y0,2));
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 + sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 + s*sqrt(ausdruck))/(1 + pow(s,2));
- if(ip->y < ym){
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 - sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 - s*sqrt(ausdruck))/(1 + pow(s,2));
- }
- }
- }
- break;
- case ELLIPSE_NODETYPE:
- x0 = middle.x;
- y0 = middle.y;
- a = width / 2;
- b = height / 2;
- ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
- ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- if(ip->y < y0){
- ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
- ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- }
- break;
- case RHOMB_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y + height;
- l2.x = pos.x + width;
- l2.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- break;
- case HEXAGON_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y + height;
- l2.x = pos.x + width - placer.hexagon[0];
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = pos.x + width;
- l1.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- default:
- break;
- }
- } else { // 3. quadrant
- switch(pathKind){
- case RECT_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y + height;
- l2.x = pos.x;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- case ROUNDRECT_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y + height;
- l2.x = pos.x + height / 3;
- l2.y = pos.y + height;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = l2.x = pos.x;
- l1.y = middle.y;
- l2.y = pos.y + height - height / 3;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- } else {
- r = height / 3;
- x0 = middle.x;
- y0 = middle.y;
- xm = pos.x + r;
- ym = pos.y + height - r;
- ausdruck = (pow(r,2) + pow(r,2)*pow(s,2) - pow(s,2)*pow(xm,2) +
- 2*pow(s,2)*xm*x0 - pow(s,2)*pow(x0,2) + 2*s*xm*ym - 2*s*x0*ym -
- pow(ym,2) - 2*s*xm*y0 + 2*s*x0*y0 + 2*ym*y0 - pow(y0,2));
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 + sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 + s*sqrt(ausdruck))/(1 + pow(s,2));
- if(ip->y < ym){
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 - sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 - s*sqrt(ausdruck))/(1 + pow(s,2));
- }
- }
- }
- break;
- case ELLIPSE_NODETYPE:
- x0 = middle.x;
- y0 = middle.y;
- a = width / 2;
- b = height / 2;
- ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
- ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- if(ip->y < y0){
- ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
- ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- }
- break;
- case RHOMB_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y + height;
- l2.x = pos.x;
- l2.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- break;
- case HEXAGON_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y + height;
- l2.x = pos.x + placer.hexagon[0];
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = pos.x;
- l1.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- default:
- break;
- }
- }
- } else {
- if(aPoint->x > middle.x){ // 1. quadrant
- switch(pathKind){
- case RECT_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y;
- l2.x = pos.x + width;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- case ROUNDRECT_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y;
- l2.x = pos.x + width - height / 3;
- l2.y = pos.y;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = l2.x = pos.x + width;
- l1.y = middle.y;
- l2.y = pos.y + height / 3;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- } else {
- r = height / 3;
- x0 = middle.x;
- y0 = middle.y;
- xm = pos.x + width - r;
- ym = pos.y + r;
- ausdruck = (pow(r,2) + pow(r,2)*pow(s,2) - pow(s,2)*pow(xm,2) +
- 2*pow(s,2)*xm*x0 - pow(s,2)*pow(x0,2) + 2*s*xm*ym - 2*s*x0*ym -
- pow(ym,2) - 2*s*xm*y0 + 2*s*x0*y0 + 2*ym*y0 - pow(y0,2));
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 + sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 + s*sqrt(ausdruck))/(1 + pow(s,2));
- if(ip->y > ym){
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 - sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 - s*sqrt(ausdruck))/(1 + pow(s,2));
- }
- }
- }
- break;
- case ELLIPSE_NODETYPE:
- x0 = middle.x;
- y0 = middle.y;
- a = width / 2;
- b = height / 2;
- ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
- ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- if(ip->y > y0){
- ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
- ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- }
- break;
- case RHOMB_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y;
- l2.x = pos.x + width;
- l2.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- break;
- case HEXAGON_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y;
- l2.x = pos.x + width - placer.hexagon[0];
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = pos.x + width;
- l1.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- default:
- break;
- }
- } else { // 2. quadrant
- switch(pathKind){
- case RECT_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y;
- l2.x = pos.x;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- case ROUNDRECT_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y;
- l2.x = pos.x + height / 3;
- l2.y = pos.y;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = l2.x = pos.x;
- l1.y = middle.y;
- l2.y = pos.y + height / 3;
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->x = l2.x;
- ip->y = middle.y + s * (ip->x - middle.x);
- } else {
- r = height / 3;
- x0 = middle.x;
- y0 = middle.y;
- xm = pos.x + r;
- ym = pos.y + r;
- ausdruck = (pow(r,2) + pow(r,2)*pow(s,2) - pow(s,2)*pow(xm,2) +
- 2*pow(s,2)*xm*x0 - pow(s,2)*pow(x0,2) + 2*s*xm*ym - 2*s*x0*ym -
- pow(ym,2) - 2*s*xm*y0 + 2*s*x0*y0 + 2*ym*y0 - pow(y0,2));
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 + sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 + s*sqrt(ausdruck))/(1 + pow(s,2));
- if(ip->y > ym){
- ip->x = (xm + pow(s,2)*x0 + s*ym - s*y0 - sqrt(ausdruck))/(1 + pow(s,2));
- ip->y = (s*xm - s*x0 + pow(s,2)*ym + y0 - s*sqrt(ausdruck))/(1 + pow(s,2));
- }
- }
- }
- break;
- case ELLIPSE_NODETYPE:
- x0 = middle.x;
- y0 = middle.y;
- a = width / 2;
- b = height / 2;
- ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
- ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- if(ip->y > y0){
- ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
- ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
- }
- break;
- case RHOMB_NODETYPE:
- l1.x = middle.x;
- l1.y = pos.y;
- l2.x = pos.x;
- l2.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- break;
- case HEXAGON_NODETYPE:
- l1.x = middle.x;
- l1.y = l2.y = pos.y;
- l2.x = pos.x + placer.hexagon[0];
- if(straddles(&l1, &l2, &middle, aPoint)){
- ip->y = l1.y;
- ip->x = middle.x + (ip->y - middle.y) / s;
- } else {
- l1.x = pos.x;
- l1.y = middle.y;
- ausdruck = (l2.y - l1.y) / (l2.x - l1.x);
- ip->x = (middle.y + ausdruck * l1.x - s * middle.x - l1.y) / (ausdruck - s);
- ip->y = middle.y + s * (ip->x - middle.x);
- }
- break;
- default:
- break;
- }
- }
- }
- return self;
- }
-
- @end
-
- //************************************************************************
- // static c functions implementation
-
- static void setRectFromPolygon(NXRect *rect, Polygon *aPol, const NXPoint *ipu, const NXPoint *ipl,
- NXCoord *low, NXCoord *loh)
- {
- NXCoord minX, minY, maxX, maxY, x, y;
- Polyline *dummy;
-
- minX = minY = 9999;
- maxX = maxY = -9999;
- dummy = aPol->upper.head;
- x = ipu->x;
- y = ipu->y;
- minX = MIN(minX, x);
- minY = MIN(minY, y);
- maxX = MAX(maxX, x);
- maxY = MAX(maxY, y);
- while(dummy){
- x += dummy->dx;
- y += dummy->dy;
- minX = MIN(minX, x);
- minY = MIN(minY, y);
- maxX = MAX(maxX, x);
- maxY = MAX(maxY, y);
- dummy = dummy->link;
- }
- dummy = aPol->lower.head;
- x = ipl->x;
- y = ipl->y;
- minX = MIN(minX, x);
- minY = MIN(minY, y);
- maxX = MAX(maxX, x);
- maxY = MAX(maxY, y);
- while(dummy){
- x += dummy->dx;
- y += dummy->dy;
- minX = MIN(minX, x);
- minY = MIN(minY, y);
- maxX = MAX(maxX, x);
- maxY = MAX(maxY, y);
- dummy = dummy->link;
- }
- NXSetRect(rect, minX, minY, maxX - minX, maxY - minY);
- *loh = ipu->y - minY;
- *low = ipu->x - minX;
- }
-
- static NXCoord merge(Polygon *c1,Polygon *c2, NXZone *zone)
- {
- NXCoord x,y,total,d;
- Polyline *lower,*upper,*b;
-
- x = y = total = 0;
- upper = c1->lower.head;
- lower = c2->upper.head;
- while(lower && upper){
- d = offset(x,y,lower->dx,lower->dy,upper->dx,upper->dy);
- y += d;
- total += d;
- if(x + lower->dx <= upper->dx){
- y += lower->dy;
- x += lower->dx;
- lower = lower->link;
- } else {
- y -= upper->dy;
- x -= upper->dx;
- upper = upper->link;
- }
- }
- if(lower){
- b = bridge(c1->upper.tail,lower,0,0,x,y,zone);
- c1->upper.tail = (b->link) ? c2->upper.tail : b;
- c1->lower.tail = c2->lower.tail;
- partialFreePolyline(c2->upper.head, lower->link);
- freePolyline(c1->lower.head);
- } else {
- b = bridge(c2->lower.tail,upper,x,y,0,0,zone);
- if(!b->link)
- c1->lower.tail = b;
- partialFreePolyline(c1->lower.head,upper->link);
- freePolyline(c2->upper.head);
- }
- c1->lower.head = c2->lower.head;
- return total;
- }
-
- static NXCoord offset(NXCoord p1,NXCoord p2,NXCoord a1,NXCoord a2,
- NXCoord b1,NXCoord b2)
- {
- NXCoord d,s,t;
-
- if(b1 <= p1 || p1 + a1 <= 0)
- return 0;
- t = b1 * a2 - a1 * b2;
- if(t > 0){
- if(p1 < 0)
- s = p1 * a2,d = s / a1 - p2;
- else if(p1 > 0)
- s = p1 * b2,d = s / b1 - p2;
- else
- d = -p2;
- } else if(b1 < p1 + a1)
- s = (b1 - p1) * a2,d = b2 - (p2 + s / a1);
- else if(b1 > p1 + a1)
- s = (a1 + p1) * b2, d = s / b1 - (p2 + a2);
- else
- d = b2 - (p2 + a2);
- return MAX(0,d);
- }
-
- static Polyline *bridge(Polyline *line1,Polyline *line2,NXCoord x1,NXCoord y1,
- NXCoord x2,NXCoord y2, NXZone *zone)
- {
- NXCoord dx,dy,s;
- Polyline *r;
-
- dx = x2 + line2->dx - x1;
- if(line2->dx == 0)
- dy = line2->dy;
- else
- s = dx * line2->dy,dy = s / line2->dx;
- r = allocLine(dx,dy,line2->link,zone);
- line1->link = allocLine(0,y2 + line2->dy -dy - y1,r,zone);
- return r;
- }
-
- static Polyline *allocLine(NXCoord aX,NXCoord aY,Polyline *aLink, NXZone *zone)
- {
- Polyline *theAlloced;
-
- theAlloced = (Polyline *)NXZoneMalloc(zone,sizeof(Polyline));
- theAlloced->dx = aX;
- theAlloced->dy = aY;
- theAlloced->link = aLink;
- return theAlloced;
- }
-
- static Polyline *copyPolyline(Polyline *aSource,Polyline **aTail, NXZone *zone)
- {
- Polyline *aLine,*l,*result;
-
- l = aSource;
- aLine = (Polyline *)NXZoneMalloc(zone,sizeof(Polyline));
- aLine->dx = l->dx;
- aLine->dy = l->dy;
- aLine->link = NULL;
- result = aLine;
- l = l->link;
- while(l){
- aLine->link = (Polyline *)NXZoneMalloc(zone,sizeof(Polyline));
- aLine = aLine->link;
- aLine->dx = l->dx;
- aLine->dy = l->dy;
- aLine->link = NULL;
- l = l->link;
- }
- *aTail = aLine;
- return result;
- }
-
- static void freePolyline(Polyline *aLine)
- {
- Polyline *index,*trailer;
-
- trailer = aLine;
- index = aLine;
- while(index){
- index = index->link;
- NX_FREE(trailer);
- trailer = index;
- }
- }
-
- static void partialFreePolyline(Polyline *aLine, Polyline *toEnd)
- {
- Polyline *index,*trailer;
-
- trailer = aLine;
- index = aLine;
- while(index && index != toEnd){
- index = index->link;
- NX_FREE(trailer);
- trailer = index;
- }
- }
-
- static BOOL straddles(const NXPoint *p1, const NXPoint *p2, const NXPoint *p3, const NXPoint *p4)
- {
- float crossP1, crossP2;
-
- crossP1 = (p3->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (p3->y - p1->y);
- crossP2 = (p4->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (p4->y - p1->y);
- if((crossP1 > 0 && crossP2 < 0) || (crossP1 < 0 && crossP2 > 0)){
- crossP1 = (p1->x - p3->x) * (p4->y - p3->y) - (p4->x - p3->x) * (p1->y - p3->y);
- crossP2 = (p2->x - p3->x) * (p4->y - p3->y) - (p4->x - p3->x) * (p2->y - p3->y);
- if((crossP1 > 0 && crossP2 < 0) || (crossP1 < 0 && crossP2 > 0))
- return YES;
- else
- return NO;
- } else
- return NO;
- }
-
-
-
-
-
-